package com.zhihuishu.micro.course.service.impl;

import com.zhihuishu.micro.course.dto.CourseFolderDto;
import com.zhihuishu.micro.course.dto.CourseFolderRootAndDirDto;
import com.zhihuishu.micro.course.helper.LogModule;
import com.zhihuishu.micro.course.helper.RemoteLogHelper;
import com.zhihuishu.micro.course.service.CCFolderTreenityDBService;
import com.zhihuishu.micro.course.service.CCFolderTreenityRedisService;
import com.zhihuishu.micro.course.service.CCFolderTreenityService;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.Comparator;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 * table-CC_FOLDER
 * dto-CourseFolder
 * @author Jiangli
 * @date 2016/12/16 13:15
 */
@Service("ccFolderTreenityService")
public class CCFolderTreenityServiceImpl extends BaseTreenityBatchServiceImpl<CourseFolderDto> implements CCFolderTreenityService {
    private final static String moduleCN = "cc文件夹";
    private final static int moduleCode = LogModule.CC_FOLDER.getCode();

    @Resource
    private CCFolderTreenityDBService ccFolderTreenityServiceDB;

    @Resource
    private CCFolderTreenityRedisService ccFolderTreenityServiceRedis;



    @Override
    protected CCFolderTreenityDBService getDBService() {
        return ccFolderTreenityServiceDB;
    }

    @Override
    protected Class<CourseFolderDto> getDTOClass() {
        return CourseFolderDto.class;
    }

    @Override
    protected CCFolderTreenityRedisService getRedisService() {
        return ccFolderTreenityServiceRedis;
    }

    @Override
    public CourseFolderRootAndDirDto findRootAndDir(Long courseId, String folderName) {
        return getDBService().findRootAndDir(courseId, folderName);
    }


    @Override
    public void update(CourseFolderDto dto, long updateUserId) {
        //unique check
        checkAndGetUniqueName(dto,"update");

        super.update(dto, updateUserId);
    }

    @Override
    public CourseFolderDto updateAndGet(CourseFolderDto dto, long updateUserId) {
        //unique check
        checkAndGetUniqueName(dto,"update");

        CourseFolderDto detailInDB = doUpdate(dto, updateUserId);

        return detailInDB;
    }

    private CourseFolderDto doUpdate(CourseFolderDto dto, long updateUserId) {
        Assert.notNull(dto);
        Integer dtoId = dto.getId();
        Assert.notNull(dtoId);

        // 更新数据库中的章
        getDBService().update(dto,updateUserId);

        //直接查库，然后更新缓存
        CourseFolderDto detailInDB = getDBService().detail(dtoId);
        log.debug("update {} from params:[{}]!" ,getDTOName(),String.valueOf(dto)) ;
        log.debug("update {} from db:[{}]!" ,getDTOName(),String.valueOf(detailInDB) ) ;

        getRedisService().update(detailInDB,updateUserId);

        log.warn("执行更新dto:[{}]，更新人[{}]!" , dtoId,updateUserId) ;
        return detailInDB;
    }


    @Override
    public Integer create(CourseFolderDto dto, long creator) {
        Assert.notNull(dto, moduleCN+"对象为空!");
        Assert.notNull(dto.getOneToManyId(), moduleCN+"所属oneToManyId为空!");
//        Assert.notNull(dto.getName(), moduleCN+"的字段-name为空!");

        //unique check
        checkAndGetUniqueName(dto,"create");

        //创建root文件夹时
        if (dto.getParentId() == null) {
            throw new IllegalArgumentException("不支持创建root文件夹!!!需要字段ParentId");
//            List<Integer> uniqueCheck = listDtoIds(dto.getOneToManyId());
//            if (!CollectionUtils.isEmpty(uniqueCheck)) {
//                throw new IllegalArgumentException(String.format("oneToManyId ID：{} 下已经存在一个:{}了",dto.getOneToManyId(),moduleCN));
//            }
        }

        RemoteLogHelper.log(moduleCode, creator, "[开始]创建"+moduleCN+"[oneToManyId ID：{}/序号：{}]", dto.getOneToManyId(), dto.getRank());

        dto.setCreateTime(new Date());//save to redis
        Integer dtoId = super.create(dto, creator);

        RemoteLogHelper.log(moduleCode, creator
                , "[完成]创建"+moduleCN+"[oneToManyIdID：{}/序号：{}]({})"
                , dto.getOneToManyId(), dto.getRank(), dtoId);
        return dtoId;
    }

    private int calcMax(List<String> names,String oldName) {
        //cal max
        int max = 0;

        if (names.size() > 0) {
            Pattern compile = Pattern.compile("(?<=\\()\\d+(?=\\))");

            for (String each : names) {
                //cut (n)
                each = each.substring(oldName.length());

                Matcher matcher = compile.matcher(each);
                matcher.find();

                String group = matcher.group();

                if (group != null) {
                    Integer current = Integer.parseInt(group);
                    if (current > max) {
                        max = current;
                    }
                }
            }

        }
        return max;
    }

    @Override
    public CourseFolderDto refreshUniqueName(CourseFolderDto dto, long updateUserId) {
        Integer id = dto.getId();
        if(!StringUtils.isEmpty(id)){
            CourseFolderDto detail = detail(id);

            String oldName = detail.getName();

            CourseFolderDto update = new CourseFolderDto();
            update.setId(id);
            update.setName(oldName);

            return updateAndGet(update, updateUserId);
        }

        return dto;
    }

    private void checkAndGetUniqueName(CourseFolderDto dto, String mode) {
        String oldFolderName = dto.getName();
        if(!StringUtils.isEmpty(oldFolderName)){

            Long parentDirId = null;

            if (mode.equals("update")) {
                Long id = dto.getId().longValue();
                parentDirId = getDBService().findFolderNameForUpdate(id,oldFolderName);
            }
            if (mode.equals("create")) {
                Long id = dto.getParentId();
                parentDirId = getDBService().findFolderNameForCreate(id,oldFolderName);
            }


            //exist  xxx
            if (parentDirId!= null) {
//                throw new IllegalArgumentException("文件夹名字重复!"+oldFolderName);

                //check xxx(n)
                List<String> folderNameLike = getDBService().findFolderNameLike(parentDirId, dto.getId(),oldFolderName + "(%)");

                //cal max
                int max = calcMax(folderNameLike,oldFolderName);

                String  newName = oldFolderName + "("+(max+1)+")";

                //update
                dto.setName(newName);
            }


        }
    }


    @Override
    protected Comparator<? super CourseFolderDto> getDtoListSorter() {
        //按名称排序
        return new  Comparator<CourseFolderDto>() {
            @Override
            public int compare(CourseFolderDto o1, CourseFolderDto o2) {
                if(o1 == null || o1.getName() == null) return 0 ;
                if(o2 == null || o2.getName() == null) return 0 ;
                return o1.getName().compareTo(o2.getName());
            }
        };

    }

    @Override
    public void sort(List<CourseFolderDto> dbDtoList, long updateUserId) {
        throw new UnsupportedOperationException("sort is not supported!!!");
    }

    @Override
    public List<Integer> findDirectChildren(List<Integer> folderIds) {
        return getDBService().findDirectChildren(folderIds);
    }

    @Override
    public List<Integer> findAllChildren(List<Integer> folderIds) {
        List<Integer> ret = new LinkedList<Integer>();
        List<Integer> directChildren = findDirectChildren(folderIds);

        while (directChildren != null && directChildren.size() > 0) {
            ret.addAll(directChildren);

            directChildren = findDirectChildren(directChildren);
        }

        return ret;
    }
}
